Fork me on GitHub

Web Push

什么是 Web Push

目前大部分浏览器已经支持 Notification API,但 Web Notification 要求用户必须在线打开 Web Page。那么如何在网页关闭情况下继续发送 Web Notification 呢,那么答案就是我们今天要介绍的基于 Service WorkerPush API 的 Web Push 技术。

实现细节

  • 用户授权:向用户请求用于接收消息推送的权限。

  • 注册 Service Worker:页面向浏览器注册一个ServiceWorker,浏览器生成对应 ServiceWorkerRegistration对象。

  • 订阅消息:页面通过 ServiceWorker 的 PushManager.subscribe 方法向 push service(FCM)订阅消息,FCM 返回 push subscription 给浏览器,浏览器找到对应的 ServiceWorker,并把 push subscription 回传给ServiceWorker。

    在订阅一个用户之前,需要采用 VAPID 协议生成一套应用服务器密钥,也被称为 VAPID 密钥,对于每个请求 Push Service 的 Web 应用服务器来说是独一无二的,Push Service 根据 VAPID 来定位哪个 Web 应用服务器触发了推送消息给哪个用户。

  • 上报 push subscription :页面获取到 push subscription 通过 Ajax 将它发送给 Web 应用服务器。

    1
    2
    3
    4
    5
    6
    7
    8
    {
    "endpoint": "https://random-push-service.com/some-kind-of-unique-id-1234/v2/",
    "keys": {
    "p256dh" :
    "BNcRdreALRFXTkOOUHK1EtK2wtaz5Ry4YfYCA_0QTpQtUbVlUls0VJXg7A8u-Ts1XbjhazAkj7I99e8QcYP7DkM=",
    "auth" : "tBHItJI5svbpez7KI4CCXg=="
    }
    }
  • 推送消息:Web 应用服务器需要推送消息时,将 push message 和 push subscription 发送给 push service(FCM)。

  • 通知:FCM 根据 push subscription 找到对应的浏览器客户端并把消息推送给它,浏览器唤醒相应的 ServiceWorker 并触发 push 事件,通知用户。

  • 取消订阅:页面在不再需要订阅消息时,可以发送 Ajax 请求通知 Web 应用服务器去清除 push subscription 并调用 PushSubscription.unsubscribe 向 push service 去取消订阅。

体验一把

我们从 https://github.com/uestc66/web-push-codelab 上 clone 代码,按文档指示步骤操作模拟一个 Web Push 的基本流程:

实现门槛

  • Service Worker:为了做到在网页关闭的情况下,还能继续发送 Notification,必须使用驻留进程,而现在 Web 驻留进程就是现在正在大力普及的 Service Worker(chrome 下打开: chrome://serviceworker-internals 查看)。

  • 浏览器必须支持 Push API 及 Notification API。目前大部分用户浏览器是基于 Chrome 内核, API 支持度还算可以。

  • HTTPS:出于安全方面的考虑,Service Worker 只能跑在 HTTPS 页面。目前大部分网站已经是 HTTPS 的了,这个问题不大。

  • 浏览器客户端和 Web 应用服务器都必须能够访问 Google Service。Push Service 的默认实现是 Google 的 FCM/GCM (查看 chrome://gcm-internals/),而目前大部分国内网络环境无法访问 Chrome 的 FCM 推送服务,所以在不翻墙的网络环境下浏览器无法完成消息订阅和推送

    • 浏览器自建 push service 对于服务器的软硬件成本不小,推送服务商倒是可以考虑为浏览器厂商提供支持标准的 Web Push Protocol 的有影响力的推送服务,类似 Google 的 FCM/GCM

      如果Web Push一直得不到支持,对于浏览器SDK来说,可以提供一套非标准的API,允许客户端(比如,手淘)推送消息给浏览器的ServiceWorker,push service则由使用浏览器SDK的客户端自行去实现。

    • 基于三方的推送工具来实现,如:onesignal

FAQ

Push && Notification

可以理解为就是 Push Servicer 和 ServiceWorker 之间,ServiceWorker 和 Web Page 之间的消息通信。

  • Push: Push Servicer 将更新的信息传递给 ServiceWorker
  • Notification: ServiceWorker 将更新的信息推送给用户

对比 Ajax 轮询、Http 长连接、WebSocket

  • Ajax 轮询是通过客户端不断向服务端发送 Http 请求,若有新消息就取回的模式保持数据实时更新,但这种方式需要服务器有很快的处理速度和资源。
  • Http 长连接是客户端向服务器发送请求后,若服务器没有新数据要发送,就不返回 response,一旦有了新数据返回了response,客户端就立刻再发一个 request,周而复始。事实上这是把 http 协议的不对称性从客户端转移到了服务端。
  • WebSocket 是 HTML5 中提出的一个新标准,客户端在发送请求时在请求头加入额外的字段,以标识这是一个基于 WebSocket 协议的连接,服务器根据这个请求头生成响应,与客户端建立起 WebSocket 连接,之后服务端有新消息时,直接向客户端推送即可。

综上,Ajax 轮询、Http 长连接、WebSocket 都依赖页面与服务器的连接,一旦页面或者浏览器关闭,连接也就关了,而 Web Push 基于 Service Worker 即使页面或者浏览器关闭,当消息到达时,也能被唤醒并显示消息。

国内哪些站点实现了 Web Push

AliExpress,Alibaba.com 作为 FCM launch 的合作伙伴,完成了 H5 消息推送的落地。

参考文档